<template>
<div class="river"></div>
</template>

<script>
import Chart from "@/utily/chart"

let text=["东吴","西晋","东晋","刘宋","齐","梁","陈","唐","南唐","北宋","南宋","元","明初","明中","明末","清初","清中","清末","现当代"];
export default {
  name: "river",
  methods:{
    draw(){
      const that =this;
      d3.csv('./data.csv', function(d){
        return {
          date: d.date,
          food: +d.food,
        };
      }).then(function(data){
        /* ----------------------------配置参数------------------------  */
        const chart = new Chart();
        console.log(chart);
        const config = {
          margins: {top: 80, left: 80, bottom: 50, right: 80},
          textColor: 'black',
          gridColor: 'gray',
          title: '基础河流图',
          animateDuration: 1000
        }

        chart.margins(config.margins);
        chart.width(850);
        chart.height(350);
        /* ----------------------------尺度转换------------------------  */
        chart.scaleX = d3.scaleTime()
            .domain([new Date(data[0].date), new Date(data[data.length-1].date)])
            .range([0, chart.getBodyWidth()]);

        chart.scaleY = d3.scaleLinear()
            .domain([0, (Math.floor((
                d3.max(data, (d) => d.food)
            )/5) )*10])
            .range([chart.getBodyHeight(), 0])

        chart.stack = d3.stack()
            .keys([ 'food',"food"])
            .order(d3.stackOrderInsideOut)
            .offset(d3.stackOffsetWiggle);

        var linearColor=["linearColor1","linearColor2"]
        /* ----------------------------渲染面------------------------  */
        chart.renderArea = function(){
          const areas = chart.body().insert('g',':first-child')
              .attr('transform', 'translate(0, -' +  d3.max(data, (d) => d3.mean(Object.values(d))) + ')')   // 使流图的位置处于Y轴中部
              .attr('transform', 'translate(0, -140)')   // 使流图的位置处于Y轴中部
              .selectAll('.area')
              .data(chart.stack(data));

          d3.select(".body")
              .attr('transform', 'translate(50,100)')
              .attr('clip-path', "url(#clip)");
          areas.enter()
              .append('path')
              .attr('class', (d) => 'area area-' + d.key)
              .merge(areas)
              .style("fill",function (d,i){return "url(#"+linearColor[i]+")"})
              .transition().duration(config.animateDuration)
              .attrTween('d', areaTween);

          //中间帧函数
          function areaTween(_d){
            if (!_d) return;
            const generateArea = d3.area()
                .x((d) => d[0])
                .y0((d) => d[1])
                .y1((d) => d[2])
                .curve(d3.curveCardinal.tension(0));

            const pointX = data.map((d) => chart.scaleX(new Date(d.date)));
            const pointY0 = _d.map((d) => chart.scaleY(d[0]));
            const pointY1 = _d.map((d) => chart.scaleY(d[1]));

            const interpolate = getAreaInterpolate(pointX, pointY0, pointY1);

            const ponits = [];

            return function(t){
              ponits.push([interpolate.x(t), interpolate.y0(t), interpolate.y1(t)]);
              return generateArea(ponits);
            }
          }

          //点插值
          function getAreaInterpolate(pointX, pointY0, pointY1){

            const domain = d3.range(0, 1, 1/(pointX.length-1));
            domain.push(1);

            const interpolateX = d3.scaleLinear()
                .domain(domain)
                .range(pointX);

            const interpolateY0 = d3.scaleLinear()
                .domain(domain)
                .range(pointY0);

            const interpolateY1 = d3.scaleLinear()
                .domain(domain)
                .range(pointY1);
            return {
              x: interpolateX,
              y0: interpolateY0,
              y1: interpolateY1
            };
          }
        }

        /* ----------------------------渲染坐标轴------------------------  */
        chart.renderX = function(){
          chart.svg().insert('g','.river')
              .attr('transform', 'translate(' + chart.bodyX() + ',' + (chart.bodyY() + chart.getBodyHeight()) + ')')
              .attr('transform', 'translate(80,205)')
              .attr("visibility","hidden")
              .attr('class', 'xAxis')
              .call(d3.axisBottom(chart.scaleX).ticks(d3.timeDay.every(3)).tickFormat((d) => d3.timeFormat("%d")(d)))
          ;
        }

        chart.renderY = function(){
          chart.svg().insert('g','.river')
              .attr('transform', 'translate(' + chart.bodyX() + ',' + chart.bodyY() + ')')
              .attr('class', 'yAxis')
              .call(d3.axisLeft(chart.scaleY));
        }

        chart.renderAxis = function(){
          chart.renderX();
        }


        function drawCirle(className,x,y,r){
          d3.select("svg")
              .append("circle")
              .attr("class",className)
              .attr('fill','#B2B0A8')
              .attr('opacity','1')
              .attr("cx", x)
              .attr("cy", y)
              .attr("r", r)
          d3.selectAll("."+className)
              .on('mouseover', function(d,i){
                const e = d3.event;
                const position = d3.mouse(chart.svg().node());
                e.target.style.cursor = 'hand'
                chart.svg()
                    .append('text')
                    .classed('tip', true)
                    .attr('x', position[0]-10)
                    .attr('y', position[1]-30)
                    .attr('fill', config.textColor)
                    .text(text[i]);
                d3.select(this)
                    .classed("shader", false)
                    .attr('fill','#333331')

              })
              .on('mouseleave', function(){
                const e = d3.event;
                d3.select('.tip').remove();
                d3.select(this)
                    .classed("shader", false)
                    .attr('fill','#B2B0A8')
              })
              .on("click",function(d,i){
                that.$bus.$emit('changetext',text[i]);
                that.$bus.$emit('changes',text[i]);
                that.$bus.$emit('changew',text[i]);
                that.$bus.$emit('changed',text[i]);
                that.$bus.$emit('changeds',text[i]);
              })
        }


        chart.addMouseOn = function(){
          d3.select(".body").append('line')
              .attr("class","hhhh")
              .attr('x1',-10)
              .attr('y1',79)
              .attr('x2',700)
              .attr('y2',79)
              .attr('style','stroke:rgb(131,121,116);stroke-width:3')
          drawCirle("tang",80,179,6);
          drawCirle("tang",110,179,5);
          drawCirle("tang",140,179,8);
          drawCirle("tang",170,179,5);
          drawCirle("tang",200,179,5);
          drawCirle("tang",230,179,9);
          drawCirle("tang",260,179,5);
          drawCirle("tang",290,179,6);
          drawCirle("tang",320,179,5);
          drawCirle("tang",350,179,6);
          drawCirle("tang",380,179,5);
          drawCirle("tang",410,179,5);
          drawCirle("tang",440,179,7);
          drawCirle("tang",470,179,7);
          drawCirle("tang",500,179,10);
          drawCirle("tang",530,179,8);
          drawCirle("tang",570,179,9);
          drawCirle("tang",610,179,10);
          drawCirle("tang",660,179,5);



          var linearGradient = d3.select("#linearColor")

          /* ----------------------------绑定鼠标交互事件------------------------  */
          //防抖函数
          function debounce(fn, time){
            let timeId = null;
            return function(){
              const context = this;
              const event = d3.event;
              timeId && clearTimeout(timeId)
              timeId = setTimeout(function(){
                d3.event = event;
                fn.apply(context, arguments);
              }, time);
            }
          }

          d3.selectAll(".area")
              .attr('fill-opacity', 0.5)
          d3.select(".area")
              .attr('fill-opacity', 1)
          d3.selectAll('.area')
              .on('mouseover', function(d){
                const e = d3.event;
                const position = d3.mouse(chart.svg().node());
                e.target.style.cursor = 'hand'

                d3.selectAll('.area')
                    .attr('opacity', 0.3);

                d3.select(e.target)
                    .attr('opacity', 1);

                d3.selectAll(".grid")
                    .attr('visibility',"visible")

                chart.svg()
                    .append('text')
                    .classed('tip', true)
                    .attr('cx', position[0]+20)
                    .attr('cy', position[1]+20)
                    .attr('fill', config.textColor)
                    .text("诗词数量");
              })
              .on('mouseleave', function(){
                const e = d3.event;
                d3.selectAll('.area')
                    .attr('opacity', 1);

                d3.select('.tip').remove();

                d3.selectAll(".grid")
                    .attr('visibility',"hidden")

                d3.select(".xAxis")
                    .attr('visibility',"hidden")
              })
              .on('mousemove', debounce(function(){
                    const position = d3.mouse(chart.svg().node());
                    d3.select('.tip')
                        .attr('x', position[0]+5)
                        .attr('y', position[1]-5);
                  }, 6)
              );
        }


        chart.render = function(){

          chart.renderAxis();

          chart.renderArea();

          chart.addMouseOn();
        }

        chart.renderChart(".river","box1");
      });
    },


  },
  mounted() {
    this.draw();
  }
}
</script>

<style>
.box1{
  position:relative;
  transform: rotate(90deg);
  margin-top: 40px;
  left: -50px;
}
.shader{
  filter: drop-shadow(16px 16px 20px red) invert(75%);
}
</style>